﻿using PublicClass;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PublicScreenMenue
{
    public partial class FormQuckCmd : Form
    {
        private int nIndex = -1;
        List<QuckCmdData> lstCmd = new List<QuckCmdData>();
        public FormQuckCmd()
        {
            InitializeComponent();
        }

        private void InitHead()
        {

        }

        private void InitData()
        {
            CPropertyCollection propertyManageCls = new CPropertyCollection();
            // 菜单转成快捷group
            List<ItemDataGroup> lst = ScreenMenu.MenuData().GetGroupList();
            foreach (ItemDataGroup item in lst)
            {
                if (item == null)
                    continue;

                QuckCmdData group = new QuckCmdData(item);
                lstCmd.Add(group);
                foreach (QuckCmdData itemChild in group.Childrens)
                {
                    if (itemChild.Command.Length == 0)
                        continue;
                    CProperty pp = new CProperty(itemChild.Text, itemChild.QCMD, false, true);
                    pp.qcmd = itemChild;
                    pp.Category = group.Text;

                    propertyManageCls.Add(pp);
                }
            }
            propertyGrid.ToolbarVisible = false;
            // propertyGrid.PropertySort = PropertySort.NoSort;
            propertyGrid.SelectedObject = propertyManageCls;
            // ucDataGridViewQuckCmd.DataSource = lstCmd;
        }

        private void FormQuckCmd_Load(object sender, EventArgs e)
        {
            InitHead();
            InitData();
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            CPropertyCollection propertyManageCls = propertyGrid.SelectedObject as CPropertyCollection;
            foreach (var item in propertyManageCls)
            {
                if (item.qcmd != null)
                    item.qcmd.QCMD = item.Value as string;
            }

            QuckCmdData.QuckCmd().Childrens = lstCmd;
            QuckCmdData.QuckCmd().Save();
            this.DialogResult = DialogResult.OK;
            QuckCmdData.ReloadLsp();
        }
    }

    public class QuckCmdData
    {
        [DisplayName("命令名")]
        public string Text { get; set; }
        [DisplayName("快捷命令")]
        public string QCMD { get; set; }
        [Browsable(false)]
        public string Command { get; set; }
        [Browsable(false)]
        public List<QuckCmdData> Childrens { get; set; }


        private static QuckCmdData qcmd = null;
        public QuckCmdData()
        {
            Init();
        }

        public static void ReloadLsp()
        {
            // 重新加载lsp
            string lsp = QuckCmdData.QuckCmdLspFile();
            lsp = lsp.Replace("\\", "\\\\"); // \ 换成 \\
            string cmd = string.Format($"(load \"{lsp}\")");
            // (load "C:\\ProgramData\\wangafeiApp\\UserAppData\\Menu.lsp")
            // 最终命令行输入的(load "C:\ProgramData\wangafeiApp\UserAppData\Menu.lsp")
            CadUnits.RunLspCmd(cmd);
        }

        void Init()
        {
            Text = "";
            QCMD = "";
            Command = "";
            Childrens = null;
        }

        public QuckCmdData(MenuItemData item)
        {
            Init();
            Text = item.Text;
            Command = item.Command;

            // 老的找到快捷定义名称
            QuckCmdData qcmd = QuckCmdData.QuckCmd(); // 老的快捷定义文件

            QuckCmdData findCmd = FindQCmdData(Command, qcmd);
            if (null != findCmd)
                QCMD = findCmd.QCMD;
        }

        public QuckCmdData(ItemDataGroup group)
        {
            Init();
            Text = group.Title;
            foreach (var item in group.GetChildLst())
            {
                if (Childrens == null)
                    Childrens = new List<QuckCmdData>();
                QuckCmdData data = new QuckCmdData(item);
                Childrens.Add(data);
            }
        }

        private static QuckCmdData FindQCmdData(string cmd, QuckCmdData qcmd = null)
        {
            // 老的找到快捷定义名称
            if (null == qcmd)
                qcmd = QuckCmdData.QuckCmd(); // 老的快捷定义文件

            if (qcmd == null)
                return null;

            if (qcmd.Command.Equals(cmd, StringComparison.OrdinalIgnoreCase))
                return qcmd;
            if (qcmd.Childrens == null)
                return null;
            foreach (var item in qcmd.Childrens)
            {
                QuckCmdData q = FindQCmdData(cmd, item);
                if (q != null)
                    return q;
            }

            return null;
        }

        public string ToStringEx()
        {
            if (QCMD.Length == 0 || Command.Length == 0)
                return "";
            // vs版底可能编译不过 如果不过
            // string.Format("(defun c:{0}{1}", QCMD, Command)
            string cmd = string.Format($"(defun c:{QCMD}() (command \"{Command}\") (princ))" +
                $"{System.Environment.NewLine}(princ)");
            return cmd;
        }

        public bool SetFromString(string str)
        {
            if (null == str || str.Length == 0)
                return false;

            if (str[0] == ';')
                return false; // 注释

            int nFind1 = str.IndexOf("c:");
            int nFind2 = str.IndexOf("()");

            if (nFind1 == -1 || nFind2 == -1)
                return false;

            // 函数名称
            QCMD = str.Substring(nFind1 + 2, (nFind2 - nFind1 - 2));

            nFind1 = str.IndexOf("\"");
            nFind2 = str.IndexOf("\"", nFind1 + 1);

            if (nFind1 == -1 || nFind2 == -1)
                return false;

            // 命令名称
            Command = str.Substring(nFind1 + 1, (nFind2 - nFind1 - 1));

            return true;   
        }

        #region 文件相关

        static public string QuckCmdLspFile()
        {
            string str = PublicNoCad.GetSelftUserPath() + "\\Menu.lsp";
            return str;
        }

        static public QuckCmdData QuckCmd()
        {
            if (null == qcmd)
            {
                qcmd = new QuckCmdData();
                qcmd.Load();
            }

            return qcmd;
        }
        private void WirteData(List<QuckCmdData> lst, StreamWriter ws)
        {
            if (null == lst)
                return;

            foreach (var item in lst)
            {
                string str = item.ToStringEx();
                if (str.Length != 0)
                    ws.WriteLine(str);

                WirteData(item.Childrens, ws);
            }
        }
        public void Save()
        {
            try
            {
                // 创建一个 StreamReader 的实例来读取文件 
                // using 语句也能关闭 StreamReader
                using (StreamWriter sr = new StreamWriter(QuckCmdLspFile(), false, System.Text.Encoding.GetEncoding("GB2312")))
                {
                    sr.WriteLine(System.Environment.NewLine);
                    WirteData(Childrens, sr);
                }
            }
            catch (Exception e)
            {
                // 向用户显示出错消息
            }
        }

        private void Load()
        {
            try
            {
                // 创建一个 StreamReader 的实例来读取文件 
                // using 语句也能关闭 StreamReader
                using (StreamReader sr = new StreamReader(QuckCmdLspFile(), System.Text.Encoding.GetEncoding("GB2312")))
                {
                    string line;
                    // 从文件读取并显示行
                    while ((line = sr.ReadLine()) != null)
                    {
                        QuckCmdData data = new QuckCmdData();
                        if (data.SetFromString(line))
                        {
                            if (data.Childrens == null)
                                Childrens = new List<QuckCmdData>();
                            Childrens.Add(data);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // 向用户显示出错消息
            }
        }
        #endregion

        #region 重写的函数

        public override bool Equals(object obj)
        {
            if (null == obj)
                return false;

            QuckCmdData data = obj as QuckCmdData;
            if (null == data)
                return false;

            return Command.Equals(data.Command, StringComparison.OrdinalIgnoreCase);
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

//         public static bool operator == (QuckCmdData left, QuckCmdData right)
//         {
//             if (null == left || right == null)
//                 return left == right;
// 
//             return left.Equals(right);
//         }
//         public static bool operator !=(QuckCmdData left, QuckCmdData right)
//         {
//             if (left == right)
//                 return false;
// 
//             return true;
//         }
        #endregion
    }
    public class CPropertyCollection : Collection<CProperty>, ICustomTypeDescriptor
    {

//         public void Add(CProperty value)
// 
//         {
//             
// 
//             base.Put(value.Name, value);
// 
//         }



        #region "TypeDescriptor"



        public String GetClassName()

        {

            return TypeDescriptor.GetClassName(this, true);

        }



        public AttributeCollection GetAttributes()

        {

            return TypeDescriptor.GetAttributes(this, true);

        }



        public String GetComponentName()

        {

            return TypeDescriptor.GetComponentName(this, true);

        }



        public TypeConverter GetConverter()

        {

            return TypeDescriptor.GetConverter(this, true);

        }



        public EventDescriptor GetDefaultEvent()

        {

            return TypeDescriptor.GetDefaultEvent(this, true);

        }



        public PropertyDescriptor GetDefaultProperty()

        {

            return TypeDescriptor.GetDefaultProperty(this, true);

        }



        public object GetEditor(Type editorBaseType)

        {

            return TypeDescriptor.GetEditor(this, editorBaseType, true);

        }



        public EventDescriptorCollection GetEvents(Attribute[] attributes)

        {

            return TypeDescriptor.GetEvents(this, attributes, true);

        }



        public EventDescriptorCollection GetEvents()

        {

            return TypeDescriptor.GetEvents(this, true);

        }



        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)

        {

            PropertyDescriptor[] propDes = new PropertyDescriptor[this.Count];

            for (int i = 0; i < this.Count; i++)
            {

                CProperty prop = (CProperty)this[i];

                propDes[i] = new CPropertyDescriptor(ref prop, attributes);

            }

            return new PropertyDescriptorCollection(propDes);

        }



        public PropertyDescriptorCollection GetProperties()

        {

            return TypeDescriptor.GetProperties(this, true);

        }



        public object GetPropertyOwner(PropertyDescriptor pd)

        {

            return this;

        }

        #endregion

    }



    public class CProperty

    {
        public QuckCmdData qcmd = null;
        private string m_Name = string.Empty;

        private bool m_bReadOnly = false;

        private bool m_bVisible = true;

        private object m_Value = null;

        private string m_Category = string.Empty;

        TypeConverter m_Converter = null;

        object m_Editor = null;





        public CProperty(string name, object value)

        {

            m_Name = name;

            m_Value = value;

        }



        public CProperty(string name, object value, bool bReadOnly, bool bVisible)

        {

            m_Name = name;

            m_Value = value;

            m_bReadOnly = bReadOnly;

            m_bVisible = bVisible;

        }



        public bool ReadOnly

        {

            get { return m_bReadOnly; }

            set { m_bReadOnly = value; }

        }



        public virtual TypeConverter Converter

        {

            get { return m_Converter; }

            set { m_Converter = value; }

        }



        public string Name

        {

            get { return m_Name; }

            set { m_Name = value; }

        }



        public bool Visible

        {

            get { return m_bVisible; }

            set { m_bVisible = value; }

        }



        public virtual object Value

        {

            get { return m_Value; }

            set { m_Value = value; }

        }



        public string Category

        {

            get { return m_Category; }

            set { m_Category = value; }

        }



        public virtual object Editor

        {

            get { return m_Editor; }

            set { m_Editor = value; }

        }

    }





    public class CPropertyDescriptor : PropertyDescriptor

    {

        CProperty m_Property;



        public CPropertyDescriptor(ref CProperty property, Attribute[] attrs)

               : base(property.Name, attrs)

        {

            m_Property = property;

        }



        #region PropertyDescriptor "region"



        public override bool CanResetValue(object component)

        {

            return false;

        }



        public override Type ComponentType

        {

            get { return null; }

        }



        public override object GetValue(object component)

        {

            return m_Property.Value;

        }



        public override string Description

        {

            get { return m_Property.Name; }

        }



        public override string Category

        {

            get { return m_Property.Category; }

        }



        public override string DisplayName

        {

            get { return m_Property.Name; }

        }



        public override bool IsReadOnly

        {

            get { return m_Property.ReadOnly; }

        }



        public override TypeConverter Converter

        {

            get { return m_Property.Converter; }

        }



        public override void ResetValue(object component)

        {

        }



        public override bool ShouldSerializeValue(object component)

        {

            return false;

        }



        public override void SetValue(object component, object value)

        {

            m_Property.Value = value;

        }



        public override Type PropertyType

        {

            get { return m_Property.Value.GetType(); }

        }



        public override object GetEditor(Type editorBaseType)

        {

            return m_Property.Editor == null ? base.GetEditor(editorBaseType) : m_Property.Editor;

        }

        #endregion

    }

}
